import {
  Color,
  MeshPhongMaterial, TextureLoader
} from "../3rdParty/three.js/build/three.module.js";

const uuidMap = new Map();

// 生成随机材质
function createMaterial( color , transparent=false, wireframe=false) {

  return new MeshPhongMaterial( { 
    color: color?color:createRandomColor(), 
    transparent: transparent, 
    opacity: 0.5,
    wireframe:wireframe
  } );

}

function createRandomColor() {

  return Math.floor( Math.random() * ( 1 << 24 ) );

}

function isNull( obj ) {
  return obj === null || obj === undefined;
}

function generateUUID( len = 36 ){
  var s = [];
  var hexDigits = "0123456789ABCDEF";
  var from = 0;
  for(var i = 0; i < len; i++){
    from = Math.floor( Math.random() * 16 );
    s[i] = hexDigits.substring( from, from + 1 );
  }
  
  if( len >= 12 ){
    s[8] = "-";
  }

  if( len >= 16 ){
    s[13] = "-";
  }

  if( len >= 24 ){
    s[18] = "-";
  }

  if( len >= 32 ){
    s[23] = "-";
  }

  var uuid = s.join("");

  while ( uuidMap.has( uuid ) ) {
    uuid = generateUUID ( len );
  }

  uuidMap.set( uuid, true );

  return uuid;
}

var link = document.createElement( 'a' );
function save( blob, filename ) {

  if ( link.href ) {

    URL.revokeObjectURL( link.href );

  }

  link.href = URL.createObjectURL( blob );
  link.download = filename || 'data.json';
  link.dispatchEvent( new MouseEvent( 'click' ) );

}

function saveArrayBuffer( buffer, filename ) {

  save( new Blob( [ buffer ], { type: 'application/octet-stream' } ), filename );

}

function saveString( text, filename ) {

  save( new Blob( [ text ], { type: 'text/plain' } ), filename );

}

// 面向X轴立方体材质索引
const CubeSideIndex = {
  All: -1,
  Front: 0,
  Back:1,
  Top:2,
  Bottom:3,
  Left:4,
  Right:5,
}

/**
 * 将材质转换为JSON格式字符串
 */
function mtlToJSON( mtl ) {

  let json;

  if( mtl.isMeshPhongMaterial ) {

    json = {

      type: "Phong",
      name: mtl.name,
      uuid: mtl.uuid,

      color: mtl.color.toArray(),
      emissive: mtl.emissive.toArray(),
      specular: mtl.specular.toArray(),
      shininess: mtl.shininess,
      transparent: mtl.transparent,
      opacity: mtl.opacity,

      texture: mtl.userData.texture,

    };

    if( mtl.map ) {

      json["map"] = {

        wrapS: mtl.map.wrapS,
        wrapT: mtl.map.wrapT,
        repeat: mtl.map.repeat.toArray(),

        offset: mtl.map.offset.toArray(),
        center: mtl.map.center.toArray(),
        rotation: mtl.map.rotation,

      }

    }

  }

  // console.log("JSON", mtl, json );
  return json;

}

/**
 * 从JSON字符串创建材质
 */
function mtlFromJSON( data ) {

  let mtl;
  const textureLoader = new TextureLoader();

  if( data.type === "Phong" ) {

    mtl = new MeshPhongMaterial({
      name: data.name,
      // uuid: data.uuid,

      color : new Color().fromArray( data.color ),
      emissive : new Color().fromArray( data.emissive ),
      specular : new Color().fromArray( data.specular ),

      shininess: data.shininess,
      transparent: data.transparent,
      opacity: data.opacity,
    });

    if( data.texture ) {
      textureLoader.load( data.texture, (texture)=>{

        if( data.map ) {
          
          texture.wrapS = data.map.wrapS;
          texture.wrapT = data.map.wrapT;
          texture.repeat.set( data.map.repeat[0], data.map.repeat[1] );

          texture.offset.set( data.map.offset[0], data.map.offset[1] );
          texture.center.set( data.map.center[0], data.map.center[1] );
          texture.rotation = data.map.rotation;
        
        }

        mtl.userData.texture = data.texture;
        mtl.map = texture;
        mtl.needsUpdate = true;

      })
    }
  }

  return mtl;

}

/**
 * 更新对象的贴图
 * @param {*} obj 
 * @param {*} config JSON格式,贴图配置文件 
 * 示例:
 * defaultTexture = {
 *   Front: {
 *     url:"../../../textures/door.jpg",
 *     size: [ -1, -1 ],
 *     offset:[0, 0],
 *     center:[0.5, 0.5],
 *     rotation:0
 *  },
 *   Back: {
 *     url:"../../../textures/door.jpg",
 *     size: [ -1, -1 ],
 *     offset:[0, 0],
 *     center:[0.5, 0.5],
 *     rotation:Math.PI
 *   }
 * }
 */
function updateObjectTexture( obj, texture ) {
  
  if( !texture || !obj ){
    return;
  }

  for( var side in texture ) {
    
    if( !(side in CubeSideIndex) ) continue;

    const url = texture[side].url;
    // const size = isNumber( texture[side].size ) ? texture[side].size : 1;
    let config = {};

    if( texture[side].size ){

      const u = texture[side].size[0];
      const v = texture[side].size[1];

      switch( side ){

        case "Top":
        case "Bottom":
          config = {
            repeat:[ u >= 0 ? this.width / u : 1, v >= 0 ? this.depth / v : 1 ],
          }
          break;
        case "Left":
        case "Right":
          config = {
            repeat:[ u >= 0 ? this.width / u : 1, v >= 0 ? this.height / v : 1 ],
          }
          break;
        case "Front":
        case "Back":
          config = {
            repeat:[ u >= 0 ? this.depth / u : 1, v >= 0 ? this.height / v : 1 ],
          }
          break;
        default:
          config = {
            repeat:[ u >= 0 ? u : 1, v >= 0 ? v : 1 ],
          }
          break;
      }

    }

    if( texture[side].offset ){
      config["offset"]= texture[side].offset;
    }
    
    if( texture[side].rotation ){
      config["rotation"]= texture[side].rotation;
    }

    if( texture[side].center ){
      config["center"]= texture[side].center;
    }

    obj.setTexture( url, CubeSideIndex[side], config );
    
  }
}
/**
 * 返回对象是否是数字
 * @param {*} obj 
 * @returns 
 */
function isNumber( obj ) {
  
  if( obj === null || obj === undefined ) return false;

  return !isNaN( obj );

}

export {
  CubeSideIndex,

  createMaterial,
  isNull,
  isNumber,
  generateUUID,
  saveString,
  saveArrayBuffer,

  mtlToJSON,
  mtlFromJSON,

  updateObjectTexture,

};